package compiler.my_parser;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/**
 * Created by szj on 2017/5/30.
 */
public class State {

    private static int stateNumCount;
    private static boolean transitionDone = false;
    private static boolean printInfo = false;
    private ProductionManager productionManager = ProductionManager.getInstance();
    private int stateNum;
    private List<Production> productions = new ArrayList<>();
    private List<Production> closure = new ArrayList<>();

    public State(List<Production> productions) {
        this.stateNum = stateNumCount;
        this.productions = productions;
        this.closure.addAll(this.productions);
    }

    public static void increaseStateNum() {
        stateNumCount++;
    }


    public void createTransition() {
        if (transitionDone) {
            return;
        }
        transitionDone = true;

        makeClosure();

        makePartition();

        makeTransition();

        printInfo = true;
    }

    private void makeClosure() {

        Stack<Production> productionStack = new Stack<>();
        productions.forEach(productionStack::push);

        System.out.println("---begin make closure----");

        while (!productionStack.empty()) {
            Production production = productionStack.pop();
            System.out.println("\nproduction on top of stack is : ");
            production.println();

            if (SymbolDefinition.isTerminal(production.getDotSymbol())) {
                System.out.println("symbol after dot is not non-terminal, ignore and process next item");
                continue;
            }

            int symbol = production.getDotSymbol();
            List<Production> closures = productionManager.getProduction(symbol);
            List<Integer> lookAhead = production.computeFirstSetOfBetaAndC();

            Iterator closure = closures.iterator();
            while (closure.hasNext()) {
                Production oldProduct = (Production) closure.next();
                /*Production newProduct = (oldProduct).cloneSelf();


                newProduct.addLookAheadSet(lookAhead);


                if (closureSet.contains(newProduct) == false) {
                    System.out.println("push and add new production to stack and closureSet");

                    closureSet.add(newProduct);
                    productionStack.push(newProduct);
                    System.out.println("Add new production:");
                    newProduct.print();
                    removeRedundantProduction(newProduct);
                } else {
                    System.out.println("the production is already exist!");
                }
*/
            }


        }

        //printClosure();
        //System.out.println("----end make closure----");

    }

    private void makePartition() {

    }

    private void makeTransition() {

    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof State)) {
            return false;
        }

        State state = (State) obj;

        return state.getProductions().size() == this.getProductions().size()
                && state.getProductions().containsAll(this.getProductions());
    }

    public int getStateNum() {
        return stateNum;
    }

    public void setStateNum(int stateNum) {
        this.stateNum = stateNum;
    }

    public List<Production> getProductions() {
        return productions;
    }

    public void setProductions(List<Production> productions) {
        this.productions = productions;
    }

    public List<Production> getClosure() {
        return closure;
    }

    public void setClosure(List<Production> closure) {
        this.closure = closure;
    }
}
